﻿/*
	Copyright 2008 CATsoft Development GmbH

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/
/*
	RTM Interaction
*/

/***********************************************************************
 RTM Interfacing classes
***********************************************************************/
function rtm( ){
	var base_url = "www.rememberthemilk.com/services/"
	var s1 = 'b281ead';
	var s2 = '8aca7c464';
	var s3 = '1dae2f34cdfd9975';
	var s4 = '931a4df8ef3b92d4';
	var s5 = "api";
	var s6 = "key"
	var frob = "";
	var token = "";
	var connected = false;
	var username = "";
	var secureHttp = false;
	var token;

/***********************************************************************
 Initializing
***********************************************************************/
rtm.prototype.setSecure = function( aSecure ){
        secure = aSecure;
}

rtm.prototype.setToken = function( aToken ){
        token = aToken;
}

rtm.prototype.getTokenValue = function (){
        return token;
}

rtm.prototype.isConnected = function(){
        return connected;
}

rtm.prototype.getUsername = function(  ){
        return username;
}

/***********************************************************************
 Convert Recurrence
***********************************************************************/
rtm.prototype.convertFrequency = function( f ){
        var i = 0, j=0;
        var s, byDay, byMonthDay, freq, interval, every;

        f = f + ";"
        i = f.indexOf("EVERY=");
        j = f.indexOf(";", i );
        every = f.substr( i+ 6, j - i - 6 );

        i = f.indexOf("FREQ=");
        j = f.indexOf(";", i );
        freq = f.substr( i+ 5, j - i - 5 );

        i = f.indexOf("INTERVAL=");
        j = f.indexOf(";", i );
        interval = f.substr( i+ 9, j - i - 9 );

        i = f.indexOf("BYDAY=");
        if( i > 0 )
        {
                j = f.indexOf(";", i );
                byDay = f.substr( i+ 6, j - i - 6 );
        }
        else
                byDay = "";
        
        i = f.indexOf("BYMONTHDAY=");
        if( i > 0 )
        {
                j = f.indexOf(";", i );
                byMonthDay = f.substr( i+ 11, j - i - 11 );
        }
        else
                byMonthDay = "";

        if(every=="1" )
        {
                s = FREQ_EVERY + " ";
                switch( freq ){
                        case "HOURLY":  s += (interval > 1) ? FREQ_HOURS : FREQ_HOUR; break;
                        case "DAILY":   s += (interval > 1) ? interval + " " + FREQ_DAYS : FREQ_DAY; break;
                        case "WEEKLY":  s += (interval > 1) ? interval + " " + ((byDay.length > 0 ) ? getWeekDay( byDay ) : FREQ_WEEKS) : ((byDay.length > 0 ) ? getWeekDay( byDay ): FREQ_WEEK); break;
                        case "MONTHLY": s += (interval > 1) ? interval + " " + FREQ_MONTHS : FREQ_MONTH + (byMonthDay > '' ? ' ' + FREQ_ONTHE + ' ' + byMonthDay : ''); break;
                        case "YEARLY":  s += (interval > 1) ? interval + " " + FREQ_YEARS : FREQ_YEAR; break;
                        default:
                                s = f.substr( 0, f.length - 1);
                }
        }
        else
         {
                s = FREQ_AFTER + " ";
                switch( freq ){
                        case "HOURLY":  s += (interval > 1) ? FREQ_HOURS : FREQ_HOUR; break;
                        case "DAILY":   s += (interval > 1) ? interval + " " + FREQ_DAYS : FREQ_DAY; break;
                        case "WEEKLY":  s += (interval > 1) ? interval + " " + ((byDay.length > 0 ) ? getWeekDay( byDay ) : FREQ_WEEKS) : ((byDay.length > 0 ) ? getWeekDay( byDay ): FREQ_WEEK); break;
                        case "MONTHLY": s += (interval > 1) ? interval + " " + ((byDay.length > 0 ) ? getWeekDay( byDay ) : FREQ_MONTHS) : ((byDay.length > 0 ) ? getWeekDay( byDay ): FREQ_MONTH); break;
                        case "YEARLY":  s += (interval > 1) ? interval + " " + FREQ_YEARS : FREQ_YEAR; break;
                        default:
                                s = f.substr( 0, f.length - 1);
                }
        }
        return s;
}

/***********************************************************************
 Create Hash
***********************************************************************/
rtm.prototype.createHash = function ( parms ){
var hashstring;
var base = s1 + s2 + s5 + "_" + s6 +  s3 + s4;
var hash;

        hashstring = base;
  for (i=0;i<parms.length;i++)
    hashstring = hashstring + parms[i].replace("=", "") ;   // Equals between parameter and value
  
        hash = hex_md5(hashstring);  
        return hash;
}

/***********************************************************************
 Get Frob
***********************************************************************/
rtm.prototype.getFrob = function() {

  var url = this.createURL( "rtm.auth.getFrob", [], "delete" );
        var parser = COMM.sendXMLHttpRequest( url );
        connected = ( parser != null );
				if(!connected) 
					return;

        if( parser.checkError(false).length == 0 ) 
                frob = parser.getValue("frob");
        return frob;
}

/***********************************************************************
 Get Token
***********************************************************************/
rtm.prototype.getToken = function (){
  var url = this.createURL("rtm.auth.getToken", ["frob=" + frob] );
        var parser = COMM.sendXMLHttpRequest( url );
        connected = ( parser != null );
				if(!connected) 
					return;
        if( parser.checkError(false).length == 0 ) 
                token = parser.getValue("token");

}

/***********************************************************************
 Checking Token
***********************************************************************/
rtm.prototype.checkToken = function (){
        var url = this.createURL("rtm.auth.checkToken", ["auth_token=" + token] );
        var parser = COMM.sendXMLHttpRequest( url );
        connected = ( parser != null );
				if(!connected) 
					return;
        if(parser == null )
                return;
        if( parser.checkError(true).length == 0 ) 
        {
                perms = parser.getValue("perms");
                if(perms != "delete")
                        token = ""
                else
                {
                        token = parser.getValue("token");
                        username = parser.getAttributeValue( "user", "username");
                }
        }
        else
                token = "";
}

/***********************************************************************
 Getting List
***********************************************************************/
rtm.prototype.getLists = function ( ){
  var url = this.createURL("rtm.lists.getList", ["auth_token=" + token] );

        var parser = COMM.sendXMLHttpRequest( url );
        connected = ( parser != null );
				if(!connected) 
					return;
				if(parser == null )
                return;
        if( parser.checkError(false).length == 0 ) 
                parser.parseLists(  );
}

/***********************************************************************
 Getting Task
***********************************************************************/
rtm.prototype.getTasks = function(lists) {
    var emptyArray = new Array();

    tasks = emptyArray;
    for (var i = 0; i < lists.length; ++i) {
        if (getListShow(lists[i].id, lists[i].position) == "true")
            this.getTasksForList(lists[i].id, lists[i].color, lists[i].filter);
    }
    tasks.sort(this.sortTasks);
}

/***********************************************************************
 Getting Tasks for List
***********************************************************************/
rtm.prototype.getTasksForList = function ( listId, listColor, listFilter )
{
        var filter = "";
        var p;
        var completed = false;
        
        if( options.exists("completedtasks" ))
                completed = (options.getValue("completedtasks") == "1" );

        if( listFilter > "" ) 
        {
                filter = listFilter.substr(1);
                filter = filter.substr(0,filter.length - 1 );
                if(!completed)
                                filter = "(" + filter + ") AND status:incomplete";
                p = [ "auth_token=" + token, "filter=" + filter ];

        }
        else
        {
                filter = "due:today OR dueBefore:today";
                if( options.getvalue("futuredays") > "0" ){
                        var i = 0;
                        i = parseInt( options.getvalue("futuredays"))  + 1;
                        filter = filter + " OR dueWithin:\"" + i + " days of today\""
                }
                if (options.getValue("nodate" ) == "1")
                        filter = filter + " OR due:never";
                if(!completed)
                                filter = "(" + filter + ") AND status:incomplete";
                p = [ "auth_token=" + token, "list_id=" + listId , "filter=" + filter];
        }
        
        var url = this.createURL( "rtm.tasks.getList", p );
        var parser = COMM.sendXMLHttpRequest( url );
        connected = ( parser != null );
        if(parser == null )             // no connection
                return;
        
        if( parser.checkError(false).length == 0 ) 
                parser.parseTasks( listId, listColor, (listFilter != "") );
        
}

/***********************************************************************
 Load Locations
***********************************************************************/
rtm.prototype.getLocations = function (){
        var url = this.createURL("rtm.locations.getList", ["auth_token=" + token] );
        var location = new Object();
        var emptyList = new Array();
        var parser = COMM.sendXMLHttpRequest( url );
        connected = ( parser != null );

        if(parser == null )
                return;
        
        locations = emptyList;
        location.id = "-1";
        location.name = NONE;
        locations.push( location );

        if( parser.checkError(false).length == 0 ) 
                parser.parseLocations( locations );
        return locations.length;
}

/***********************************************************************
 Load Locations
***********************************************************************/
rtm.prototype.getTimeline = function (){
        var p =  [ "auth_token=" + token ];
        var timeline;
        var url = this.createURL( "rtm.timelines.create", p );

        var parser = COMM.sendXMLHttpRequest( url );
        connected = ( parser != null );
        if( parser.checkError(false).length == 0 ) 
                timeline = parser.getValue("timeline");
        else
                alert( "Error getting timeline: " + parser.checkError(false));
        return timeline;
}

/***********************************************************************
Add List
***********************************************************************/
rtm.prototype.addList = function(listName) {
    var timeline = this.getTimeline();
    var taskItem;

    if (timeline != null) {
        var p2 = ["auth_token=" + token, "name=" + listName, "timeline=" + timeline];
        url = this.createURL("rtm.lists.add", p2);
        var parser = COMM.sendXMLHttpRequestAsync(url);
       /* connected = (parser != null);
        if (parser.checkError(false).length != 0)
            alert("Error adding task: " + parser.checkError(false));*/
    }
}

/***********************************************************************
 Add Task
***********************************************************************/
rtm.prototype.addTask = function( task ){
        var timeline = this.getTimeline();
        var taskItem;

        if(timeline != null)
        {
                var p2 = [ "auth_token=" + token, "list_id=" + task.listid, "name=" + task.name, "timeline=" + timeline ];
                url = this.createURL( "rtm.tasks.add", p2 );
                var parser = COMM.sendXMLHttpRequest( url );
                connected = ( parser != null );
                if( parser.checkError(false).length != 0 ) 
                        alert( "Error adding task: " + parser.checkError(false));
                else
                        taskItem = parser.parseAddTasks( task.listid );
        }
        return taskItem;
}

/***********************************************************************
 Add Smart Task
***********************************************************************/
rtm.prototype.addSmartTask = function( listid, taskname ){
        var timeline = this.getTimeline();
        var taskItem;

        if(timeline != null)
        {
                var p2 = [ "auth_token=" + token, "list_id=" +listid, "name=" + taskname, "parse=1", "timeline=" + timeline ];
                url = this.createURL( "rtm.tasks.add", p2 );
                var parser = COMM.sendXMLHttpRequest( url );
                connected = ( parser != null );
                if( parser.checkError(false).length != 0 ) 
                        alert( "Error adding task: " + parser.checkError(false));
                else
                        taskItem = parser.parseAddTasks( listid );
        }
        return taskItem;
}

/***********************************************************************
 Update Task
***********************************************************************/
rtm.prototype.updateTask = function(task, taskid, taskseriesid, listid) {
    var timeline = this.getTimeline();
    
    if (!this.updateTaskItem(taskid, taskseriesid, listid, "setName", timeline, ["name"], [task.name]))
        return false;
    if (!this.updateTaskItem(taskid, taskseriesid, listid, "setPriority", timeline, ["priority"], [task.priority]))
        return false;

    if (task.due.length > 0) {
        var pos = task.due.lastIndexOf(" ");
        var time = task.due.substr(pos + 1).toLowerCase();
        var hasTime = "0";
        var parse = "1";

        // Check for valid time
        if (pos > 0) {
            if ((time.indexOf(":") > 0) || (time.indexOf("pm") > 0) || (time.indexOf("am") > 0))
                hasTime = "1"
            else {
                if (parseFloat(time) < 24)
                    hasTime = "1"
            }
        }
        //if (hasTime == "0")
        //    parse = "0";
        // Parse foreign language month name
        task.due = parseMonthName(task.due);

        if (!this.updateTaskItem(taskid, taskseriesid, listid, "setDueDate", timeline, ["due", "parse", "has_due_time"], [task.due, parse, hasTime]))
            return false;
    }
    if (!this.updateTaskItem(taskid, taskseriesid, listid, "setRecurrence", timeline, ["repeat"], [task.repeat]))
        return false;
    if (!this.updateTaskItem(taskid, taskseriesid, listid, "setEstimate", timeline, ["estimate"], [task.estimate]))
        return false;
    if (task.location > '')
        if (!this.updateTaskItem(taskid, taskseriesid, listid, "setLocation", timeline, ["location_id"], [task.location]))
        return false;
    if (!this.updateTaskItem(taskid, taskseriesid, listid, "setTags", timeline, ["tags"], [task.tags]))
        return false;
    if (!this.updateTaskItem(taskid, taskseriesid, listid, "setURL", timeline, ["url"], [task.url]))
        return false;
}

/***********************************************************************
 Update Task Item
***********************************************************************/
rtm.prototype.updateTaskItem = function ( taskid, taskseriesid, listid, method, timeline, property, value ){
        var p2
        var ret = false

        p2 = [ "auth_token=" + token, "list_id=" + listid, "task_id=" + taskid, "taskseries_id=" + taskseriesid, "timeline=" + timeline]
        for( var i = 0; i < property.length; i++ )
                p2.push( property[i] + "=" + value[i] );
        url = this.createURL( "rtm.tasks." + method, p2 );
        var parser = COMM.sendXMLHttpRequest( url );
        connected = ( parser != null );
        if( parser.checkError(false).length != 0 ) 
                alert( "Error calling " + method + ": " + parser.checkError(false));
        else
                ret = true;
        return ret;
}

/***********************************************************************
 Move Task
***********************************************************************/
rtm.prototype.moveTask = function( task, listid){
        var p2;
        var ret = false;
        var timeline = this.getTimeline();

        p2 = [ "auth_token=" + token, "from_list_id=" + tasks[task].listid, "to_list_id=" + listid, "task_id=" + tasks[task].id, "taskseries_id=" + tasks[task].seriesid, "timeline=" + timeline]
        
        url = this.createURL( "rtm.tasks.moveTo", p2 );
        var parser = COMM.sendXMLHttpRequestAsync( url );
     /*   connected = ( parser != null );
        if( parser.checkError(false).length != 0 ) 
                alert( "Error calling rtm.tasks.moveTo: " + parser.checkError(false));
        else
                ret = true;
        return ret;*/
}


/***********************************************************************
        Mark Task as finished
***********************************************************************/
rtm.prototype.fixIt = function( task ){

        var p =  [ "auth_token=" + token ];

        var url = this.createURL( "rtm.timelines.create", p );
        var parser = COMM.sendXMLHttpRequest( url );
        connected = ( parser != null );
        if( parser.checkError(false).length == 0 ) 
        {
                var timeline = parser.getValue("timeline");
                var p2 = [ "auth_token=" + token, "list_id=" + tasks[task].listid, "task_id=" + tasks[task].id, "taskseries_id=" + tasks[task].seriesid, "timeline=" + timeline ];
                url = this.createURL( "rtm.tasks.complete", p2 );

                var parser = COMM.sendXMLHttpRequest( url );
                connected = ( parser != null );

                if( parser.checkError(false).length != 0 ) 
                        alert( "Error marking task as fixed: " + parser.checkError(false));
        
        }
        else
                alert( "Error getting Timeline: " + parser.checkError(false));

}

/***********************************************************************
        Postpone Task
***********************************************************************/
rtm.prototype.postPone = function( task )
{
        var p =  [ "auth_token=" + token ];
        var url = this.createURL( "rtm.timelines.create", p );

        var parser = COMM.sendXMLHttpRequest( url );
        connected = ( parser != null );
        if( parser.checkError(false).length == 0 ) 
        {
                var timeline = parser.getValue("timeline");
                var p2 = [ "auth_token=" + token, "list_id=" + tasks[task].listid, "task_id=" + tasks[task].id, "taskseries_id=" + tasks[task].seriesid, "timeline=" + timeline ];
                url = this.createURL( "rtm.tasks.postpone", p2 );

                parser = COMM.sendXMLHttpRequest( url );
                connected = ( parser != null );

                if( parser.checkError(false).length != 0 ) 
                        alert( "Error postponing task: " + parser.checkError(false));
        
        }
        else
                alert( "Error getting Timeline: " + parser.checkError(false));
}


/***********************************************************************
        Parse Time
***********************************************************************/
rtm.prototype.parseTime = function( ts ){
        var p = [ "auth_token=" + token, "text=" + ts ]
        var url = this.createURL( "rtm.time.parse", p );

        var parser = COMM.sendXMLHttpRequest( url );
        connected = ( parser != null );
        if( parser.checkError(false).length != 0 ) 
        {
                alert( "Error parsing time: " + parser.checkError(false));
                var d = new Date();
        }
        else
        {
                var dateString = parser.getValue("time");
                var d = new Date( dateString.substr( 0, 4 ), parseFloat(dateString.substr(5,2)) - 1, dateString.substr(8,2));
        }
        return d;
}

/***********************************************************************
        Sorting Tasks
***********************************************************************/
rtm.prototype.sortTasks = function(a, b) {
    var ret = 0;
    var td = new Date();
    var sortBy = 1;

    if (options.exists("sortby"))
        sortBy = parseInt(options.getValue("sortby"))
        
    switch (sortBy) {
        case 0: /* Priority */
            if (a.priority > b.priority)
                ret = 1
            else if (a.priority < b.priority)
                ret = -1
            else
                if (a.name > b.name)
                ret = 1
            else if (a.name > b.name)
                ret = -1;
            break;
        case 1: /* Due Date */
            if ((a.completed.length > 0) && (b.completed.length == 0))
                ret = 1
            else if ((a.completed.length == 0) && (b.completed.length > 0))
                ret = -1
            else {
                if (a.dueIn == -9999)   // Due Never
                    ret = 1;
                else if (b.dueIn == -9999)
                    ret = -1;
                else if (todayOnTop) {
                    if ((a.dueIn == 0) && (b.dueIn == 0)) {      // Both are today
                        if (Date.parse(a.due) > Date.parse(b.due))          // Sort by date
                            ret = 1
                        else if (Date.parse(a.due) < Date.parse(b.due))
                            ret = -1;
                    }
                    else {

                        if (a.dueIn == 0)
                            ret = -1
                        else if (b.dueIn == 0)
                            ret = 1
                        else if (a.due > b.due) // Normal sort    
                            ret = 1
                        else if (a.due < b.due)
                            ret = -1
                        else if (a.name.toLowerCase() > b.name.toLowerCase())
                            ret = 1
                        else if (a.name.toLowerCase() > b.name.toLowerCase())
                            ret = -1
                        else
                            ret = 1;
                    }
                }
                else {
                    if (a.due > b.due)
                        ret = 1
                    else if (a.due < b.due)
                        ret = -1
                    else if (a.name.toLowerCase() > b.name.toLowerCase())
                        ret = 1
                    else if (a.name.toLowerCase() > b.name.toLowerCase())
                        ret = -1;
                }
            }
            break;
        case 2: /* By Name */
            if (a.name.toLowerCase() > b.name.toLowerCase())
                ret = 1
            else if (a.name.toLowerCase() < b.name.toLowerCase())
                ret = -1;
            break;
        case 3:  /* By Tag Name */
            if (a.tags.toLowerCase() > b.tags.toLowerCase())
                ret = 1
            else if (a.tags.toLowerCase() < b.tags.toLowerCase())
                ret = -1;
            break;
    }

    return ret;
}


/***********************************************************************
        Create URL with param
***********************************************************************/
rtm.prototype.createURL = function(method, params, perms) {
    if (perms == "undefined")
        perms = "";
    var url = "";

    if (secureHttp)
        url = "https://"
    else
        url = "http://"
    url = url + base_url
    var s = "";

    if (method > "")
        url = url + "rest/?"
    else
        url = url + "auth/?";

    url = url + s5 + "_" + s6 + "=" + s3 + s4;

    for (i = 0; i < params.length; i++) {
        if (params[i].substr(0, 5) == "name=")
            url = url + "&name=" + escape(params[i].substr(5)).replace('+', '%2B');
        else
            url = url + "&" + params[i];
    }

    if (method > "") {
        url = url + "&method=" + method;
        params[params.length] = "method=" + method;
    }

    if (perms > "") {
        params[params.length] = "perms=" + perms;
        url = url + "&perms=" + perms;
    }

    params.sort();
    hash = this.createHash(params);
    return url + "&api_sig=" + hash;
}

/***********************************************************************
  Get DateFormat
***********************************************************************/
rtm.prototype.getDateformat = function(){
       var p =  [ "auth_token=" + token ];
        var usDate;
        var url = this.createURL( "rtm.settings.getList", p );

		var parser = COMM.sendXMLHttpRequest( url );
        connected = ( parser != null );
        if( parser.checkError(false).length == 0 ) 
                usDate = (parser.getValue("dateformat") == 1 )
        else
                alert( "Error getting dateformat: " + parser.checkError(false));
        return usDate;
}

/***********************************************************************
Get TimeFormat
***********************************************************************/
rtm.prototype.getTimeformat = function() {
    var p = ["auth_token=" + token];
    var usDate;
    var url = this.createURL("rtm.settings.getList", p);

    var parser = COMM.sendXMLHttpRequest(url);
    connected = (parser != null);
    if (parser.checkError(false).length == 0)
        Time24 = (parser.getValue("timeformat") == 1)
    else
        alert("Error getting timeformat: " + parser.checkError(false));
    return Time24;
}

}
